package com.sc.nft.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.*;
import com.sc.nft.dto.DrawPrizeDTO;
import com.sc.nft.dto.EcologyHatchConfDao;
import com.sc.nft.dto.PrizeDTO;
import com.sc.nft.dto.TaskPrizeDTO;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.task.LinkDTO;
import com.sc.nft.entity.vo.BoxGroupVO;
import com.sc.nft.entity.vo.QueryBoxConditionVO;
import com.sc.nft.entity.vo.TaskListVO;
import com.sc.nft.entity.vo.WhetherUserMeetsRedemptionConditionsVO;
import com.sc.nft.enums.*;
import com.sc.nft.enums.task.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 任务表服务接口实现
 *
 * @author 张翔宇
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2023-03-29 11:14:52
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class TaskServiceImpl implements TaskService {

    private final TaskDao taskDao;

    private final TaskPrizeDao taskPrizeDao;

    private final TaskAppointProductDao taskAppointProductDao;

    private final EquityPropsDao equityPropsDao;

    private final TaskPanelDao taskPanelDao;

    private final DigitalCollectionDao digitalCollectionDao;

    private final UserCollectionDao userCollectionDao;

    private final TaskPlanDao taskPlanDao;

    private final TaskDrawPrizeDao taskDrawPrizeDao;

    private final UserAssetsService userAssetsService;

    private final UserEquityPropsService equityPropsService;

    private final BoxTakePoolDao boxTakePoolDao;

    private final BoxItemService boxItemService;

    private final ProductStockDao productStockDao;

    private final ProductStockService productStockService;

    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;

    private final UserCollectionService userCollectionService;

    private final BoxProductDao boxProductDao;

    private final MallProductDao mallProductDao;

    private final BoxTakeConversionConditionService boxTakeConversionConditionService;

    private final FilterIncomeListDao filterIncomeListDao;
    private final EcologyHatchConfDao ecologyHatchConfDao;


    private final EcologyPoolService ecologyPoolService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addTask(String taskIcon, Integer taskPlan, String taskName, Long taskPanelId, Long buyCollectionId, Integer inviteCount, Long partakeCollectionId, ParticipantsEnum participants, Integer superiorLimit, Date taskStartDate, Date taskEndDate, List<TaskPrizeDTO> taskPrizeDTOS, Integer sort, BigDecimal totalPrice, Boolean collectionRange, Boolean mallRange, List<Long> linkIds) {
        TaskPanel taskPanel = taskPanelDao.getById(taskPanelId);
        Assert.notNull(taskPanel, () -> new GlobalRunTimeException("任务模板不存在"));
        Assert.isTrue(taskPanel.getStatus(), () -> new GlobalRunTimeException("任务模板已下架"));
        if (taskPanel.getType() == TaskTypeEnum.NEW_AUTH || taskPanel.getType() == TaskTypeEnum.NEW_BUY) {
            superiorLimit = 1;
        } else if (superiorLimit == null) {
            throw new GlobalRunTimeException("请输入完成次数限制");
        }
        if (taskPanel.getType() == TaskTypeEnum.BUY_APPOINT || taskPanel.getType() == TaskTypeEnum.TOTAL_BUY || taskPanel.getType() == TaskTypeEnum.TOTAL_SPEND) {
            if (totalPrice == null || NumberUtil.isLessOrEqual(totalPrice, BigDecimal.ZERO)) {
                throw new GlobalRunTimeException("累计金额不正确");
            }
        }
        Task task = new Task();
        task.setTaskPanelId(taskPanelId);
        task.setDaoId(6L);
        task.setAuthorityTask(true);
        task.setTaskIcon(taskIcon);
        task.setTaskName(taskName);
        task.setTaskPlan(taskPlan);
        task.setTotalPrice(totalPrice);
        task.setType(taskPanel.getType());
        task.setStatus(false);
        task.setSort(sort);
        task.setTaskStartDate(taskStartDate);
        task.setTaskEndDate(taskEndDate);
        task.setSuperiorLimit(superiorLimit);
        task.setParticipants(participants);
        task.setAudit(1);
        if (task.getParticipants() == ParticipantsEnum.APPOINT && partakeCollectionId == null) {
            throw new GlobalRunTimeException("请选择参与商品");
        }
        task.setPartakeCollectionId(partakeCollectionId);
        List<TaskAppointProduct> appointProducts = Lists.newArrayList();
        switch (task.getType()) {
            case OPENING:
                if (inviteCount == null || inviteCount <= 0) {
                    throw new GlobalRunTimeException("邀请人数不正确");
                }
                task.setInviteCount(inviteCount);
                break;
            case DAO:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择藏品");
                DigitalCollection digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                task.setInviteCount(inviteCount);
                break;
            case AD:
                break;
            case NEW_AUTH:
                task.setInviteCount(1);
                break;
            case NEW_BUY:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择藏品");
                digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                break;
            case USER_BOW_PIN:
                task.setSuperiorLimit(1);
                break;
            case BOW_PIN_USER_BOW_PINY:
                break;
            case BUY_APPOINT:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定藏品");
                }
                List<DigitalCollection> digitalCollections = digitalCollectionDao.getByIds(linkIds);
                Assert.isTrue(digitalCollections.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的藏品"));
                for (DigitalCollection digitalCollection1 : digitalCollections) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(digitalCollection1.getId());
                    appointProduct.setLinkName(digitalCollection1.getFirstTitle());
                    appointProduct.setLinkImage(digitalCollection1.getCreationContent());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_BUY:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定商品");
                }
                List<MallProduct> mallProducts = mallProductDao.getByIds(linkIds);
                Assert.isTrue(mallProducts.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的商品"));
                for (MallProduct mallProduct : mallProducts) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(mallProduct.getId());
                    appointProduct.setLinkName(mallProduct.getProductName());
                    appointProduct.setLinkImage(mallProduct.getThumbnail());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_SPEND:
                if (collectionRange == null && mallRange) {
                    throw new GlobalRunTimeException("请选择任务范围");
                }
                task.setCollectionRange(collectionRange);
                task.setMallRange(mallRange);
                task.setTotalPrice(totalPrice);
                break;
            default:
                throw new GlobalRunTimeException("任务类型不正确");
        }
        task.insert();
        for (TaskAppointProduct appointProduct : appointProducts) {
            appointProduct.setTaskId(task.getId());
            appointProduct.insert();
        }
        insertTaskPrize(taskPrizeDTOS, task);
    }

    @Override
    public void addMerchantTask(String taskIcon, Integer taskPlan, String taskName, Long taskPanelId, Long buyCollectionId, Integer inviteCount, Long partakeCollectionId, ParticipantsEnum participants, Integer superiorLimit, Date taskStartDate, Date taskEndDate, List<TaskPrizeDTO> taskPrizeDTOS, Integer sort, Long daoId, BigDecimal totalPrice, Boolean collectionRange, Boolean mallRange, List<Long> linkIds) {
        TaskPanel taskPanel = taskPanelDao.getById(taskPanelId);
        Assert.notNull(taskPanel, () -> new GlobalRunTimeException("任务模板不存在"));
        Assert.isTrue(taskPanel.getStatus(), () -> new GlobalRunTimeException("任务模板已下架"));
        Assert.isTrue(taskPanel.getBusinessUseStatus(), () -> new GlobalRunTimeException("任务模板禁止使用"));
        if (taskPanel.getType() == TaskTypeEnum.NEW_AUTH || taskPanel.getType() == TaskTypeEnum.NEW_BUY) {
            superiorLimit = 1;
        } else if (superiorLimit == null) {
            throw new GlobalRunTimeException("请输入完成次数限制");
        }
        if (taskPanel.getType() == TaskTypeEnum.BUY_APPOINT || taskPanel.getType() == TaskTypeEnum.TOTAL_BUY || taskPanel.getType() == TaskTypeEnum.TOTAL_SPEND) {
            if (totalPrice == null || NumberUtil.isLessOrEqual(totalPrice, BigDecimal.ZERO)) {
                throw new GlobalRunTimeException("累计金额不正确");
            }
        }
        Task task = new Task();
        task.setTaskPanelId(taskPanelId);
        task.setDaoId(daoId);
        task.setAuthorityTask(true);
        task.setTaskIcon(taskIcon);
        task.setTaskName(taskName);
        task.setType(taskPanel.getType());
        task.setTaskPlan(taskPlan);
        task.setTotalPrice(totalPrice);
        task.setStatus(false);
        task.setSort(sort);
        task.setTaskStartDate(taskStartDate);
        task.setTaskEndDate(taskEndDate);
        task.setSuperiorLimit(superiorLimit);
        task.setParticipants(participants);
        task.setAudit(0);
        if (task.getParticipants() == ParticipantsEnum.APPOINT && partakeCollectionId == null) {
            throw new GlobalRunTimeException("请选择参与商品");
        }
        task.setPartakeCollectionId(partakeCollectionId);
        List<TaskAppointProduct> appointProducts = Lists.newArrayList();
        switch (task.getType()) {
            case OPENING:
                if (inviteCount == null || inviteCount <= 0) {
                    throw new GlobalRunTimeException("邀请人数不正确");
                }
                task.setInviteCount(inviteCount);
                break;
            case DAO:

                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择藏品");
                DigitalCollection digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                task.setInviteCount(inviteCount);
                break;
            case AD:
                break;
            case NEW_AUTH:
                task.setInviteCount(1);
                break;
            case NEW_BUY:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择藏品");
                digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                break;
            case BUY_APPOINT:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定藏品");
                }
                List<DigitalCollection> digitalCollections = digitalCollectionDao.getByIds(linkIds);
                Assert.isTrue(digitalCollections.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的藏品"));
                for (DigitalCollection digitalCollection1 : digitalCollections) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(digitalCollection1.getId());
                    appointProduct.setLinkName(digitalCollection1.getFirstTitle());
                    appointProduct.setLinkImage(digitalCollection1.getCreationContent());

                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_BUY:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定商品");
                }
                List<MallProduct> mallProducts = mallProductDao.getByIds(linkIds);
                Assert.isTrue(mallProducts.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的商品"));
                for (MallProduct mallProduct : mallProducts) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(mallProduct.getId());
                    appointProduct.setLinkName(mallProduct.getProductName());
                    appointProduct.setLinkImage(mallProduct.getThumbnail());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_SPEND:
                if (collectionRange == null && mallRange) {
                    throw new GlobalRunTimeException("请选择任务范围");
                }
                task.setCollectionRange(collectionRange);
                task.setMallRange(mallRange);
                task.setTotalPrice(totalPrice);
                break;
            default:
                throw new GlobalRunTimeException("任务类型不正确");
        }
        task.insert();
        for (TaskAppointProduct appointProduct : appointProducts) {
            appointProduct.setTaskId(task.getId());
            appointProduct.insert();
        }
        insertTaskPrize(taskPrizeDTOS, task);
    }

    @Override
    public Task getById(Long id) {
        return taskDao.getById(id);
    }

    private void insertTaskPrize(List<TaskPrizeDTO> taskPrizeDTOS, Task task) {
        for (TaskPrizeDTO taskPrizeDTO : taskPrizeDTOS) {
            switch (taskPrizeDTO.getType()) {
                case INTEGRAL:
                    TaskPrize taskPrize = new TaskPrize();
                    taskPrize.setType(taskPrizeDTO.getType());
                    taskPrize.setTaskId(task.getId());
                    taskPrize.setTouristsPrize(taskPrizeDTO.getTouristsPrize());
                    taskPrize.setCityPrize(taskPrizeDTO.getCityPrize());
                    taskPrize.setResidentPrize(taskPrizeDTO.getResidentPrize());
                    taskPrize.insert();
                    break;
                case PROPS:
                    EquityProps equityProps = equityPropsDao.getById(taskPrizeDTO.getPropsId());
                    if (ObjectUtil.isNull(equityProps)) {
                        throw new GlobalRunTimeException("奖品不存在");
                    }
                    taskPrize = new TaskPrize();
                    taskPrize.setType(taskPrizeDTO.getType());
                    Assert.isTrue(equityProps.getStatus(), () -> new GlobalRunTimeException("奖品已下架"));
                    taskPrize.setTaskId(task.getId());
                    taskPrize.setEquityId(equityProps.getId());
                    taskPrize.setPropType(equityProps.getTypeClassify());
                    taskPrize.setTouristsPrize(taskPrizeDTO.getTouristsPrize());
                    taskPrize.setCityPrize(taskPrizeDTO.getCityPrize());
                    taskPrize.setResidentPrize(taskPrizeDTO.getResidentPrize());
                    taskPrize.insert();
                    break;
                default:
                    throw new GlobalRunTimeException("奖品类型不正确");
            }
        }
    }

    @Override
    public void editTask(Long id, String taskIcon, Integer taskPlan, String taskName, Long taskPanelId, Long buyCollectionId, Integer inviteCount, Long partakeCollectionId, ParticipantsEnum participants, Integer superiorLimit, Date taskStartDate, Date taskEndDate, List<TaskPrizeDTO> taskPrizeDTOS, Integer sort, BigDecimal totalPrice, Boolean collectionRange, Boolean mallRange, List<Long> linkIds) {
        Task task = taskDao.getById(id);
        Assert.notNull(task, () -> new GlobalRunTimeException("任务不存在"));
        //上架状态不可编辑
        Assert.isFalse(task.getStatus(), () -> new GlobalRunTimeException("上架状态不可编辑"));
        TaskPanel taskPanel = taskPanelDao.getById(taskPanelId);
        Assert.notNull(taskPanel, () -> new GlobalRunTimeException("任务模板不存在"));
        Assert.isTrue(taskPanel.getStatus(), () -> new GlobalRunTimeException("任务模板已下架"));
        if (taskPanel.getType() == TaskTypeEnum.NEW_AUTH || taskPanel.getType() == TaskTypeEnum.NEW_BUY) {
            superiorLimit = 1;
        } else if (superiorLimit == null) {
            throw new GlobalRunTimeException("请输入完成次数限制");
        }
        if (taskPanel.getType() == TaskTypeEnum.BUY_APPOINT || taskPanel.getType() == TaskTypeEnum.TOTAL_BUY || taskPanel.getType() == TaskTypeEnum.TOTAL_SPEND) {
            if (totalPrice == null || NumberUtil.isLessOrEqual(totalPrice, BigDecimal.ZERO)) {
                throw new GlobalRunTimeException("累计金额不正确");
            }
        }
        task.setTaskPanelId(taskPanelId);
        task.setTaskIcon(taskIcon);
        task.setTaskName(taskName);
        task.setTaskPlan(taskPlan);
        task.setSort(sort);
        task.setTotalPrice(totalPrice);
        task.setType(taskPanel.getType());
        task.setTaskStartDate(taskStartDate);
        task.setTaskEndDate(taskEndDate);
        task.setSuperiorLimit(superiorLimit);
        task.setParticipants(participants);
        if (task.getParticipants() == ParticipantsEnum.APPOINT && partakeCollectionId == null) {
            throw new GlobalRunTimeException("请选择参与商品");
        }
        task.setPartakeCollectionId(partakeCollectionId);
        List<TaskAppointProduct> appointProducts = Lists.newArrayList();
        switch (task.getType()) {
            case DAO:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择商品");
                DigitalCollection digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                task.setInviteCount(inviteCount);
                break;
            case OPENING:
                if (inviteCount == null || inviteCount <= 0) {
                    throw new GlobalRunTimeException("邀请人数不正确");
                }
                task.setInviteCount(inviteCount);
                break;
            case AD:
                break;
            case NEW_AUTH:
                task.setInviteCount(1);
                break;
            case NEW_BUY:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择藏品");
                digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                break;
            case USER_BOW_PIN:
                task.setSuperiorLimit(1);
                break;
            case BOW_PIN_USER_BOW_PINY:
                break;
            case BUY_APPOINT:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定藏品");
                }
                List<DigitalCollection> digitalCollections = digitalCollectionDao.getByIds(linkIds);
                Assert.isTrue(digitalCollections.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的藏品"));
                for (DigitalCollection digitalCollection1 : digitalCollections) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(digitalCollection1.getId());
                    appointProduct.setLinkName(digitalCollection1.getFirstTitle());
                    appointProduct.setLinkImage(digitalCollection1.getCreationContent());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_BUY:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定商品");
                }
                List<MallProduct> mallProducts = mallProductDao.getByIds(linkIds);
                Assert.isTrue(mallProducts.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的商品"));
                for (MallProduct mallProduct : mallProducts) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(mallProduct.getId());
                    appointProduct.setLinkName(mallProduct.getProductName());
                    appointProduct.setLinkImage(mallProduct.getThumbnail());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_SPEND:
                if (collectionRange == null && mallRange) {
                    throw new GlobalRunTimeException("请选择任务范围");
                }
                task.setCollectionRange(collectionRange);
                task.setMallRange(mallRange);
                task.setTotalPrice(totalPrice);
                break;
            default:
                throw new GlobalRunTimeException("任务类型不正确");
        }
        task.updateById();
        taskAppointProductDao.clearByTaskId(task.getId());
        for (TaskAppointProduct appointProduct : appointProducts) {
            appointProduct.setTaskId(task.getId());
            appointProduct.insert();
        }
        taskPrizeDao.deleteByTaskId(task.getId());
        insertTaskPrize(taskPrizeDTOS, task);
    }

    @Override
    public void editMerchantTask(Long id, Integer taskPlan, String taskIcon, String taskName, Long taskPanelId, Long buyCollectionId, Integer inviteCount, Long partakeCollectionId, ParticipantsEnum participants, Integer superiorLimit, Date taskStartDate, Date taskEndDate, List<TaskPrizeDTO> taskPrizeDTOS, Integer sort, BigDecimal totalPrice, Boolean collectionRange, Boolean mallRange, List<Long> linkIds) {
        Task task = taskDao.getById(id);
        Assert.notNull(task, () -> new GlobalRunTimeException("任务不存在"));
        //上架状态不可编辑
        Assert.isFalse(task.getStatus(), () -> new GlobalRunTimeException("上架状态不可编辑"));
        TaskPanel taskPanel = taskPanelDao.getById(taskPanelId);
        Assert.notNull(taskPanel, () -> new GlobalRunTimeException("任务模板不存在"));
        Assert.isTrue(taskPanel.getStatus(), () -> new GlobalRunTimeException("任务模板已下架"));
        if (taskPanel.getType() == TaskTypeEnum.NEW_AUTH || taskPanel.getType() == TaskTypeEnum.NEW_BUY) {
            superiorLimit = 1;
        } else if (superiorLimit == null) {
            throw new GlobalRunTimeException("请输入完成次数限制");
        }
        if (taskPanel.getType() == TaskTypeEnum.BUY_APPOINT || taskPanel.getType() == TaskTypeEnum.TOTAL_BUY || taskPanel.getType() == TaskTypeEnum.TOTAL_SPEND) {
            if (totalPrice == null || NumberUtil.isLessOrEqual(totalPrice, BigDecimal.ZERO)) {
                throw new GlobalRunTimeException("累计金额不正确");
            }
        }
        task.setTaskPanelId(taskPanelId);
        task.setTaskIcon(taskIcon);
        task.setTaskName(taskName);
        task.setTaskPlan(taskPlan);
        task.setTotalPrice(totalPrice);
        task.setSort(sort);
        task.setType(taskPanel.getType());
        task.setTaskStartDate(taskStartDate);
        task.setTaskEndDate(taskEndDate);
        task.setSuperiorLimit(superiorLimit);
        task.setParticipants(participants);
        task.setAudit(0);
        if (task.getParticipants() == ParticipantsEnum.APPOINT && partakeCollectionId == null) {
            throw new GlobalRunTimeException("请选择参与商品");
        }
        task.setPartakeCollectionId(partakeCollectionId);
        List<TaskAppointProduct> appointProducts = Lists.newArrayList();
        switch (task.getType()) {
            case DAO:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择商品");
                DigitalCollection digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                task.setInviteCount(inviteCount);
                break;
            case OPENING:
                if (inviteCount == null || inviteCount <= 0) {
                    throw new GlobalRunTimeException("邀请人数不正确");
                }
                task.setInviteCount(inviteCount);
                break;
            case AD:
                break;
            case NEW_AUTH:
                task.setInviteCount(1);
                break;
            case NEW_BUY:
                if (buyCollectionId == null)
                    throw new GlobalRunTimeException("请选择藏品");
                digitalCollection = digitalCollectionDao.getById(buyCollectionId);
                //判断商品是存在
                Assert.notNull(digitalCollection, () -> new GlobalRunTimeException("商品不存在"));
                task.setBuyCollectionId(buyCollectionId);
                break;
            case BUY_APPOINT:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定藏品");
                }
                List<DigitalCollection> digitalCollections = digitalCollectionDao.getByIds(linkIds);
                Assert.isTrue(digitalCollections.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的藏品"));
                for (DigitalCollection digitalCollection1 : digitalCollections) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(digitalCollection1.getId());
                    appointProduct.setLinkName(digitalCollection1.getFirstTitle());
                    appointProduct.setLinkImage(digitalCollection1.getCreationContent());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_BUY:
                if (CollUtil.isEmpty(linkIds)) {
                    throw new GlobalRunTimeException("请选择指定商品");
                }
                List<MallProduct> mallProducts = mallProductDao.getByIds(linkIds);
                Assert.isTrue(mallProducts.size() == linkIds.size(), () -> new GlobalRunTimeException("列表中包含不存在的商品"));
                for (MallProduct mallProduct : mallProducts) {
                    TaskAppointProduct appointProduct = new TaskAppointProduct();
                    appointProduct.setLinkId(mallProduct.getId());
                    appointProduct.setLinkName(mallProduct.getProductName());
                    appointProduct.setLinkImage(mallProduct.getThumbnail());
                    appointProducts.add(appointProduct);
                }
                task.setTotalPrice(totalPrice);
                break;
            case TOTAL_SPEND:
                if (collectionRange == null && mallRange) {
                    throw new GlobalRunTimeException("请选择任务范围");
                }
                task.setCollectionRange(collectionRange);
                task.setMallRange(mallRange);
                task.setTotalPrice(totalPrice);
                break;
            default:
                throw new GlobalRunTimeException("任务类型不正确");
        }
        task.updateById();
        task.updateById();
        taskAppointProductDao.clearByTaskId(task.getId());
        for (TaskAppointProduct appointProduct : appointProducts) {
            appointProduct.setTaskId(task.getId());
            appointProduct.insert();
        }
        taskPrizeDao.deleteByTaskId(task.getId());
        insertTaskPrize(taskPrizeDTOS, task);
    }

    @Override
    public Page<Task> taskPage(String name, Boolean status, Long daoId, int pageNo, int pageSize) {
        return taskDao.taskPage(name, status, daoId, pageNo, pageSize);
    }

    @Override
    public Page<Task> taskMerchantPage(String name, Boolean status, Long daoId, int pageNo, int pageSize) {
        return taskDao.taskMerchantPage(name, status, daoId, pageNo, pageSize);
    }

    @Override
    public void changeTaskOrder(Long id, Integer sort) {
        Task task = new Task();
        task.setId(id);
        task.setSort(sort);
        task.updateById();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditMerchantTask(Long id, Integer status, String reason) {
        Task task = taskDao.getById(id);
        Assert.notNull(task, () -> new GlobalRunTimeException("任务不存在"));
        Assert.isFalse(task.getStatus(), () -> new GlobalRunTimeException("上架状态不可审核"));
        task.setAudit(status);
        task.setReason(reason);
        task.updateById();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delTask(Long id) {
        Task task = taskDao.getById(id);
        Assert.notNull(task, () -> new GlobalRunTimeException("任务不存在"));
        Assert.isFalse(task.getStatus(), () -> new GlobalRunTimeException("上架状态不可删除"));
        task.deleteById();
        taskPrizeDao.deleteByTaskId(task.getId());

    }

    @Override
    public void updateStatus(Long id, Boolean status) {
        Task task = taskDao.getById(id);
        Assert.notNull(task, () -> new GlobalRunTimeException("任务不存在"));
        Assert.isFalse(!task.getAudit().equals(1), () -> new GlobalRunTimeException("审核未通过"));
        task.setStatus(status);
        task.updateById();
    }

    @Override
    public List<Task> getUserTaskList(UserInfo userInfo) {
        Map<ParticipantsEnum, List<Task>> todayTask = getTodayTask();
        List<Task> taskList = Lists.newArrayList();
        if (todayTask.containsKey(ParticipantsEnum.UNLIMITED)) {
            taskList.addAll(todayTask.get(ParticipantsEnum.UNLIMITED));
        }
        if (todayTask.containsKey(ParticipantsEnum.APPOINT)) {
            List<Task> appointTask = todayTask.get(ParticipantsEnum.APPOINT);
            if (CollUtil.isNotEmpty(appointTask)) {
                List<Long> holdCollectionId = userCollectionDao.getHoldCollectionId(userInfo.getId());
                if (CollUtil.isNotEmpty(holdCollectionId)) {
                    for (Task task : appointTask) {
                        if (holdCollectionId.contains(task.getPartakeCollectionId())) {
                            taskList.add(task);
                        }
                    }
                }
            }
        }
        //实名用户过滤实名任务
        if (userInfo.getIsSm()) {
            taskList.removeAll(taskList.stream().filter(x -> x.getType() == TaskTypeEnum.NEW_AUTH).collect(Collectors.toList()));
        }

        if (userInfo.getIsValid()) {
            taskList.removeAll(taskList.stream().filter(x -> x.getType() == TaskTypeEnum.USER_BOW_PIN).collect(Collectors.toList()));
        }
        // 过滤已购买过藏品的新人任务
        List<Task> buyTask = taskList.stream().filter(x -> x.getType() == TaskTypeEnum.NEW_BUY).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(buyTask)) {
            List<Long> holdCollectionIdFormOrder = userCollectionDao.getHoldCollectionIdFormOrder(userInfo.getId());
            if (CollUtil.isNotEmpty(holdCollectionIdFormOrder)) {
                for (Task task : buyTask) {
                    if (holdCollectionIdFormOrder.contains(task.getBuyCollectionId())) {
                        taskList.remove(task);
                    }
                }
            }
        }
        return taskList;
    }


    public List<Task> getUserTaskList(UserInfo userInfo, Boolean isAudit) {
        Map<ParticipantsEnum, List<Task>> todayTask = getTodayTask(isAudit);
        List<Task> taskList = Lists.newArrayList();
        if (todayTask.containsKey(ParticipantsEnum.UNLIMITED)) {
            taskList.addAll(todayTask.get(ParticipantsEnum.UNLIMITED));
        }
        if (todayTask.containsKey(ParticipantsEnum.APPOINT)) {
            List<Task> appointTask = todayTask.get(ParticipantsEnum.APPOINT);
            if (CollUtil.isNotEmpty(appointTask)) {
                List<Long> holdCollectionId = userCollectionDao.getHoldCollectionId(userInfo.getId());
                if (CollUtil.isNotEmpty(holdCollectionId)) {
                    for (Task task : appointTask) {
                        if (holdCollectionId.contains(task.getPartakeCollectionId())) {
                            taskList.add(task);
                        }
                    }
                }
            }
        }
        //实名用户过滤实名任务
        if (userInfo.getIsSm()) {
            taskList.removeAll(taskList.stream().filter(x -> x.getType() == TaskTypeEnum.NEW_AUTH).collect(Collectors.toList()));
        }
        // 过滤已购买过藏品的新人任务
        List<Task> buyTask = taskList.stream().filter(x -> x.getType() == TaskTypeEnum.NEW_BUY).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(buyTask)) {
            List<Long> holdCollectionIdFormOrder = userCollectionDao.getHoldCollectionIdFormOrder(userInfo.getId());
            if (CollUtil.isNotEmpty(holdCollectionIdFormOrder)) {
                for (Task task : buyTask) {
                    if (holdCollectionIdFormOrder.contains(task.getBuyCollectionId())) {
                        taskList.remove(task);
                    }
                }
            }
        }
        return taskList;
    }

    public List<Task> getUserTaskList(UserInfo userInfo, TaskTypeEnum taskType) {
        Map<ParticipantsEnum, List<Task>> todayTask = getTodayTask(taskType);
        List<Task> taskList = Lists.newArrayList();
        if (todayTask.containsKey(ParticipantsEnum.UNLIMITED)) {
            taskList.addAll(todayTask.get(ParticipantsEnum.UNLIMITED));
        }
        if (todayTask.containsKey(ParticipantsEnum.APPOINT)) {
            List<Task> appointTask = todayTask.get(ParticipantsEnum.APPOINT);
            if (CollUtil.isNotEmpty(appointTask)) {
                List<Long> holdCollectionId = userCollectionDao.getHoldCollectionId(userInfo.getId());
                if (CollUtil.isNotEmpty(holdCollectionId)) {
                    for (Task task : appointTask) {
                        if (holdCollectionId.contains(task.getPartakeCollectionId())) {
                            taskList.add(task);
                        }
                    }
                }
            }
        }
        return taskList;
    }

    @Override
    public List<TaskListVO> getUserTaskListVO(UserInfo userInfo) {
        DateTime today = DateTime.now();
        List<Task> userTaskList = getUserTaskList(userInfo);
        if (CollUtil.isEmpty(userTaskList)) {
            return Lists.newArrayList();
        }
        List<TaskListVO> result = Lists.newArrayList();
        for (Task task : userTaskList) {
            TaskListVO vo = new TaskListVO();
            vo.setId(task.getId());
            vo.setTaskName(task.getTaskName());
            vo.setType(task.getType());
            vo.setBuyCollectionId(task.getBuyCollectionId());
            TaskPanel taskPanel = taskPanelDao.getById(task.getTaskPanelId());
            vo.setButtonName(taskPanel.getButtonUnFinish());
            vo.setTaskIcon(task.getTaskIcon());
            vo.setTaskPlan(task.getTaskPlan());
            vo.setPriority(false);
            vo.setFinishCount(taskPlanDao.selectUserTaskFinishCount(userInfo.getId(), task.getId(), today));
            vo.setTaskSumCount(task.getSuperiorLimit());
            vo.setStatus(vo.getFinishCount() >= vo.getTaskSumCount());
            if (vo.getType() == TaskTypeEnum.OPENING || vo.getType() == TaskTypeEnum.DAO) {
                TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), task.getId(), today);
                if (ObjectUtil.isNotNull(taskPlan)) {
                    vo.setCurrentPlan(taskPlan.getTaskCurrentPlan());
                    vo.setCurrentPlanString(String.valueOf(taskPlan.getTaskCurrentPlan().intValue()));
                } else {
                    vo.setCurrentPlan(BigDecimal.ZERO);
                    vo.setCurrentPlanString("0");
                }
                vo.setSumPlan(BigDecimal.valueOf(task.getInviteCount()));
                vo.setSumPlanString(task.getInviteCount().toString());
            } else if (vo.getType() == TaskTypeEnum.BUY_APPOINT || vo.getType() == TaskTypeEnum.TOTAL_BUY || vo.getType() == TaskTypeEnum.TOTAL_SPEND) {
                TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), task.getId(), today);
                if (ObjectUtil.isNotNull(taskPlan)) {
                    vo.setCurrentPlan(taskPlan.getTaskCurrentPlan());
                    vo.setCurrentPlanString(taskPlan.getTaskCurrentPlan().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
                } else {
                    vo.setCurrentPlan(BigDecimal.ZERO);
                    vo.setCurrentPlanString("0");
                }
                vo.setSumPlan(task.getTotalPrice());
                vo.setSumPlanString(String.valueOf(task.getTotalPrice()));
                List<TaskAppointProduct> appointProductList = taskAppointProductDao.getByTaskId(task.getId());
                List<LinkDTO> linkDTOS = Lists.newArrayList();
                for (TaskAppointProduct appointProduct : appointProductList) {
                    linkDTOS.add(new LinkDTO(appointProduct.getLinkId(), appointProduct.getLinkName(), appointProduct.getLinkImage()));
                }
                vo.setLinkDTOList(linkDTOS);
                vo.setSumPlan(task.getTotalPrice());
                vo.setSumPlanString(task.getTotalPrice().setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
            } else {
                TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), task.getId(), today);
                if (ObjectUtil.isNotNull(taskPlan)) {
                    vo.setCurrentPlan(BigDecimal.ONE);
                    vo.setCurrentPlanString("1");
                } else {
                    vo.setCurrentPlan(BigDecimal.ZERO);
                    vo.setCurrentPlanString("0");
                }
                vo.setSumPlan(BigDecimal.ONE);
                vo.setSumPlanString("1");
            }
            if (NumberUtil.isGreater(vo.getSumPlan(), BigDecimal.ONE)) {
                vo.setShowProgress(true);
            } else {
                vo.setShowProgress(false);
            }
            List<TaskPrize> taskPrize = taskPrizeDao.getTaskPrize(task.getId());
            if (CollUtil.isEmpty(taskPrize)) {
                continue;
            }
            List<PrizeDTO> taskPrizes = Lists.newArrayList();
            for (TaskPrize prize : taskPrize) {
                PrizeDTO prizeVO = new PrizeDTO();
                prizeVO.setType(prize.getType());
                if (prizeVO.getType() == TaskPrizeTypeEnum.INTEGRAL) {
                    prizeVO.setPropsName(prizeVO.getType().getDescription());
                    switch (userInfo.getLevel()) {
                        case TOURISTS:
                            prizeVO.setQuantity(prize.getTouristsPrize());
                            break;
                        case RESIDENT:
                            prizeVO.setQuantity(prize.getResidentPrize());
                            break;
                        case CITY_LORD:
                            prizeVO.setQuantity(prize.getCityPrize());
                            break;
                        default:
                            continue;
                    }
                } else {
                    EquityProps props = equityPropsDao.getById(prize.getEquityId());
                    if (ObjectUtil.isNull(props)) {
                        continue;
                    }
                    prizeVO.setPropsName(props.getFirstTitle());
                    switch (userInfo.getLevel()) {
                        case TOURISTS:
                            prizeVO.setQuantity(prize.getTouristsPrize());
                            break;
                        case RESIDENT:
                            prizeVO.setQuantity(prize.getResidentPrize());

                            break;
                        case CITY_LORD:
                            prizeVO.setQuantity(prize.getCityPrize());
                            break;
                        default:
                            continue;
                    }
                }
                taskPrizes.add(prizeVO);

            }
            vo.setTaskPrizes(taskPrizes);
            result.add(vo);
        }

        Map<TaskTypeEnum, List<TaskListVO>> collect = result.stream().collect(Collectors.groupingBy(TaskListVO::getType));
        for (Map.Entry<TaskTypeEnum, List<TaskListVO>> taskTypeEnumListEntry : collect.entrySet()) {
            if (taskTypeEnumListEntry.getValue().size() > 1) {
                if (taskTypeEnumListEntry.getKey() == TaskTypeEnum.DAO || taskTypeEnumListEntry.getKey() == TaskTypeEnum.NEW_BUY) {
                    Map<Long, List<TaskListVO>> collection = taskTypeEnumListEntry.getValue().stream().collect(Collectors.groupingBy(TaskListVO::getBuyCollectionId));
                    for (Map.Entry<Long, List<TaskListVO>> longListEntry : collection.entrySet()) {
                        if (longListEntry.getValue().size() > 1) {
                            List<Long> ids = longListEntry.getValue().stream().map(TaskListVO::getId).collect(Collectors.toList());
                            Long min = CollUtil.min(ids);
                            for (TaskListVO taskListVO : longListEntry.getValue()) {
                                if (taskListVO.getId().longValue() == min.longValue()) {
                                    taskListVO.setPriority(true);
                                }
                            }
                        }
                    }
                } else {
                    List<Long> ids = taskTypeEnumListEntry.getValue().stream().map(TaskListVO::getId).collect(Collectors.toList());
                    Long min = CollUtil.min(ids);
                    for (TaskListVO taskListVO : taskTypeEnumListEntry.getValue()) {
                        if (taskListVO.getId().longValue() == min.longValue()) {
                            taskListVO.setPriority(true);
                        }
                    }
                }

            }
        }
        return result;
    }

    @Override
    public List<TaskListVO> getUserMerchantTaskListVO(UserInfo userInfo) {
        DateTime today = DateTime.now();
        List<Task> userTaskList = getUserTaskList(userInfo, false);
        if (CollUtil.isEmpty(userTaskList)) {
            return Lists.newArrayList();
        }
        List<TaskListVO> result = Lists.newArrayList();
        for (Task task : userTaskList) {
            TaskListVO vo = new TaskListVO();
            vo.setId(task.getId());
            vo.setTaskName(task.getTaskName());
            vo.setTaskPlan(task.getTaskPlan());
            vo.setType(task.getType());
            vo.setBuyCollectionId(task.getBuyCollectionId());
            TaskPanel taskPanel = taskPanelDao.getById(task.getTaskPanelId());
            vo.setButtonName(taskPanel.getButtonUnFinish());
            vo.setTaskIcon(task.getTaskIcon());
            vo.setPriority(false);
            vo.setFinishCount(taskPlanDao.selectUserTaskFinishCount(userInfo.getId(), task.getId(), today));
            vo.setTaskSumCount(task.getSuperiorLimit());
            vo.setStatus(vo.getFinishCount() >= vo.getTaskSumCount());
            if (vo.getType() == TaskTypeEnum.OPENING || vo.getType() == TaskTypeEnum.DAO) {
                TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), task.getId(), today);
                if (ObjectUtil.isNotNull(taskPlan)) {
                    vo.setCurrentPlan(taskPlan.getTaskCurrentPlan());
                } else {
                    vo.setCurrentPlan(BigDecimal.ZERO);
                }
                vo.setSumPlan(BigDecimal.valueOf(task.getInviteCount()));
            } else if (vo.getType() == TaskTypeEnum.BUY_APPOINT || vo.getType() == TaskTypeEnum.TOTAL_BUY || vo.getType() == TaskTypeEnum.TOTAL_SPEND) {
                TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), task.getId(), today);
                if (ObjectUtil.isNotNull(taskPlan)) {
                    vo.setCurrentPlan(taskPlan.getTaskCurrentPlan());
                } else {
                    vo.setCurrentPlan(BigDecimal.ZERO);
                }
                vo.setSumPlan(task.getTotalPrice());
                List<TaskAppointProduct> appointProductList = taskAppointProductDao.getByTaskId(task.getId());
                List<LinkDTO> linkDTOS = Lists.newArrayList();
                for (TaskAppointProduct appointProduct : appointProductList) {
                    linkDTOS.add(new LinkDTO(appointProduct.getLinkId(), appointProduct.getLinkName(), appointProduct.getLinkImage()));
                }
            } else {
                TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), task.getId(), today);
                if (ObjectUtil.isNotNull(taskPlan)) {
                    vo.setCurrentPlan(BigDecimal.ONE);
                } else {
                    vo.setCurrentPlan(BigDecimal.ZERO);
                }
                vo.setSumPlan(BigDecimal.ONE);
            }
            if (NumberUtil.isGreater(vo.getSumPlan(), BigDecimal.ONE)) {
                vo.setShowProgress(true);
            } else {
                vo.setShowProgress(false);
            }
            List<TaskPrize> taskPrize = taskPrizeDao.getTaskPrize(task.getId());
            if (CollUtil.isEmpty(taskPrize)) {
                continue;
            }
            List<PrizeDTO> taskPrizes = Lists.newArrayList();
            for (TaskPrize prize : taskPrize) {
                PrizeDTO prizeVO = new PrizeDTO();
                prizeVO.setType(prize.getType());
                if (prizeVO.getType() == TaskPrizeTypeEnum.INTEGRAL) {
                    prizeVO.setPropsName(prizeVO.getType().getDescription());
                    switch (userInfo.getLevel()) {
                        case TOURISTS:
                            prizeVO.setQuantity(prize.getTouristsPrize());
                            break;
                        case RESIDENT:
                            prizeVO.setQuantity(prize.getResidentPrize());
                            break;
                        case CITY_LORD:
                            prizeVO.setQuantity(prize.getCityPrize());
                            break;
                        default:
                            continue;
                    }
                } else {
                    EquityProps props = equityPropsDao.getById(prize.getEquityId());
                    if (ObjectUtil.isNull(props)) {
                        continue;
                    }
                    prizeVO.setPropsName(props.getFirstTitle());
                    switch (userInfo.getLevel()) {
                        case TOURISTS:
                            prizeVO.setQuantity(prize.getTouristsPrize());
                            break;
                        case RESIDENT:
                            prizeVO.setQuantity(prize.getResidentPrize());

                            break;
                        case CITY_LORD:
                            prizeVO.setQuantity(prize.getCityPrize());
                            break;
                        default:
                            continue;
                    }
                }
                taskPrizes.add(prizeVO);

            }
            vo.setTaskPrizes(taskPrizes);
            result.add(vo);
        }

        Map<TaskTypeEnum, List<TaskListVO>> collect = result.stream().collect(Collectors.groupingBy(TaskListVO::getType));
        for (Map.Entry<TaskTypeEnum, List<TaskListVO>> taskTypeEnumListEntry : collect.entrySet()) {
            if (taskTypeEnumListEntry.getValue().size() > 1) {
                if (taskTypeEnumListEntry.getKey() == TaskTypeEnum.DAO || taskTypeEnumListEntry.getKey() == TaskTypeEnum.NEW_BUY) {
                    Map<Long, List<TaskListVO>> collection = taskTypeEnumListEntry.getValue().stream().collect(Collectors.groupingBy(TaskListVO::getBuyCollectionId));
                    for (Map.Entry<Long, List<TaskListVO>> longListEntry : collection.entrySet()) {
                        if (longListEntry.getValue().size() > 1) {
                            List<Long> ids = longListEntry.getValue().stream().map(TaskListVO::getId).collect(Collectors.toList());
                            Long min = CollUtil.min(ids);
                            for (TaskListVO taskListVO : longListEntry.getValue()) {
                                if (taskListVO.getId().longValue() == min.longValue()) {
                                    taskListVO.setPriority(true);
                                }
                            }
                        }
                    }
                } else {
                    List<Long> ids = taskTypeEnumListEntry.getValue().stream().map(TaskListVO::getId).collect(Collectors.toList());
                    Long min = CollUtil.min(ids);
                    for (TaskListVO taskListVO : taskTypeEnumListEntry.getValue()) {
                        if (taskListVO.getId().longValue() == min.longValue()) {
                            taskListVO.setPriority(true);
                        }
                    }
                }

            }
        }
        return result;
    }

    @Override
    public List<TaskDrawPrize> getTaskPrize(UserInfo userInfo) {
        return taskDrawPrizeDao.getTaskPrize(userInfo.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void drawPrize(UserInfo user, Long id) {
        TaskDrawPrize taskDrawPrize = taskDrawPrizeDao.getById(id);
        Assert.notNull(taskDrawPrize, () -> new GlobalRunTimeException("奖品不存在"));
        Assert.isFalse(taskDrawPrize.getStatus(), () -> new GlobalRunTimeException("奖品已领取"));
        taskDrawPrize.setStatus(true);
        taskDrawPrize.updateById();
        switch (taskDrawPrize.getPrizeType()) {
            case INTEGRAL:
                userAssetsService.addIntegralByUserId(taskDrawPrize.getPrizeCount(), user.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.TASK, taskDrawPrize.getId(), taskDrawPrize.getTaskName());
                break;
            case PROPS:
                EquityProps equityProps = equityPropsDao.getById(taskDrawPrize.getEquityId());
                //todo 任务道具获取类型待处理
                UserEquityPropsGetTypeEnum getType = UserEquityPropsGetTypeEnum.Task;

                if (taskDrawPrize.getDrawType() == DrawPriceTypeEnum.PLEDGE) {
                    getType = UserEquityPropsGetTypeEnum.PLEDGE;
                } else if (taskDrawPrize.getDrawType() == DrawPriceTypeEnum.SAAS_TASK) {
                    getType = UserEquityPropsGetTypeEnum.SAAS_TASK;
                }

                equityPropsService.addEquityPropsByUser(equityProps, user.getId(), getType, taskDrawPrize.getPrizeCount().intValue(), taskDrawPrize.getTaskName(),
                        taskDrawPrize.getTaskPlanId(), BigDecimal.ZERO, getType, taskDrawPrize.getTaskPlanId());
                break;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finishTask(UserInfo userInfo, TaskOrderTypeEnum type, @NotNull TaskTypeEnum taskType, Long linkId, Long collectionId, BigDecimal price) {
        if (filterIncomeListDao.getIsContainsUserId(userInfo.getId())) {
            return;
        }

        DateTime today = DateTime.now();
        List<Task> todayTask = getUserTaskList(userInfo, taskType);
        if (CollUtil.isEmpty(todayTask)) {
            return;
        }
        Task thisTask = null;
        //筛选任务
        for (Task task : todayTask) {
            if (task.getType() == TaskTypeEnum.DAO || task.getType() == TaskTypeEnum.NEW_BUY) {
                if (!task.getBuyCollectionId().equals(collectionId)) {
                    continue;
                }
            }
            if (task.getType() == TaskTypeEnum.BUY_APPOINT || task.getType() == TaskTypeEnum.TOTAL_BUY) {
                if (!taskAppointProductDao.existsAppointProduct(task.getId(), collectionId)) {
                    continue;
                }
            }
            if (task.getType() == TaskTypeEnum.TOTAL_SPEND) {
                switch (type) {
                    case FIRST:
                        if (!task.getCollectionRange()) {
                            continue;
                        }
                        break;
                    case SECOND:
                        if (!task.getCollectionRange()) {
                            continue;
                        }
                        break;
                    case MALL:
                        if (!task.getMallRange()) {
                            continue;
                        }
                        break;
                    default:
                        continue;
                }
            }
            Integer count = taskPlanDao.selectUserTaskFinishCount(userInfo.getId(), task.getId(), today);
            if (count >= task.getSuperiorLimit()) {
                continue;
            }
            thisTask = task;
            break;
        }
        if (ObjectUtil.isNull(thisTask)) {
            return;
        }
        log.info("命中任务:{}", thisTask.getTaskName());
        TaskPlan taskPlan = taskPlanDao.selectUserTaskPlan(userInfo.getId(), thisTask.getId(), today);
        if (ObjectUtil.isNull(taskPlan)) {
            taskPlan = new TaskPlan();
            taskPlan.setUserId(userInfo.getId());
            taskPlan.setTaskId(thisTask.getId());
            taskPlan.setTaskType(taskType);
            taskPlan.setTaskCurrentPlan(BigDecimal.ZERO);
            if (taskType == TaskTypeEnum.OPENING || taskType == TaskTypeEnum.DAO) {
                taskPlan.setTaskFinishCondition(BigDecimal.valueOf(thisTask.getInviteCount()));
            } else if (taskType == TaskTypeEnum.BUY_APPOINT || taskType == TaskTypeEnum.TOTAL_BUY || taskType == TaskTypeEnum.TOTAL_SPEND) {
                taskPlan.setTaskFinishCondition(thisTask.getTotalPrice());
            } else {
                taskPlan.setTaskFinishCondition(BigDecimal.ONE);
            }
            if (thisTask.getTaskPlan().intValue() == 0) {
                taskPlan.setTaskDate(today);
            } else if (thisTask.getTaskPlan().intValue() == 1) {
                taskPlan.setTaskDate(DateUtil.beginOfDay(DateUtil.endOfWeek(today)));
            } else {
                taskPlan.setTaskDate(today);
            }

            taskPlan.setStatus(false);
            taskPlan.insert();
        }

        if (taskType == TaskTypeEnum.BUY_APPOINT || taskType == TaskTypeEnum.TOTAL_BUY || taskType == TaskTypeEnum.TOTAL_SPEND) {
            taskPlan.setTaskCurrentPlan(taskPlan.getTaskCurrentPlan().add(price));
        } else {
            taskPlan.setTaskCurrentPlan(taskPlan.getTaskCurrentPlan().add(BigDecimal.ONE));
        }

        BigDecimal moreThanPlan = BigDecimal.ZERO;
        if (NumberUtil.isGreaterOrEqual(taskPlan.getTaskCurrentPlan(), taskPlan.getTaskFinishCondition())) {
            taskPlan.setStatus(true);
            taskPlan.setTaskFinishTime(DateTime.now());
            if (NumberUtil.isGreater(taskPlan.getTaskCurrentPlan(), taskPlan.getTaskFinishCondition())) {
                moreThanPlan = taskPlan.getTaskCurrentPlan().subtract(taskPlan.getTaskFinishCondition());
                taskPlan.setTaskCurrentPlan(taskPlan.getTaskFinishCondition());
            }


            TaskPlanRecord taskPlanRecord = new TaskPlanRecord();
            taskPlanRecord.setTaskId(thisTask.getId());
            taskPlanRecord.setUserId(userInfo.getId());
            taskPlanRecord.setPlanDate(today);
            taskPlanRecord.setLinkType(taskType);
            taskPlanRecord.setLinkId(linkId);
            taskPlanRecord.insert();

            //创建奖励
            List<TaskPrize> taskPrize = taskPrizeDao.getTaskPrize(thisTask.getId());
            for (TaskPrize prize : taskPrize) {
                TaskDrawPrize taskDrawPrize = new TaskDrawPrize();
                taskDrawPrize.setTaskId(thisTask.getId());
                taskDrawPrize.setDrawType(DrawPriceTypeEnum.TASK);
                taskDrawPrize.setUserId(userInfo.getId());
                taskDrawPrize.setTaskPlanId(taskPlan.getId());
                taskDrawPrize.setTaskName(thisTask.getTaskName());
                taskDrawPrize.setPrizeType(prize.getType());
                if (prize.getType() == TaskPrizeTypeEnum.PROPS) {
                    EquityProps equityProps = equityPropsDao.getById(prize.getEquityId());
                    taskDrawPrize.setProductIcon(equityProps.getCreationContent());
                }
                taskDrawPrize.setStatus(false);
                taskDrawPrize.setEquityId(prize.getEquityId());
                switch (userInfo.getLevel()) {
                    case TOURISTS:
                        taskDrawPrize.setPrizeCount(BigDecimal.valueOf(prize.getTouristsPrize()));
                        break;
                    case RESIDENT:
                        taskDrawPrize.setPrizeCount(BigDecimal.valueOf(prize.getResidentPrize()));
                        break;
                    case CITY_LORD:
                        taskDrawPrize.setPrizeCount(BigDecimal.valueOf(prize.getCityPrize()));
                        break;
                    default:
                        continue;
                }
                taskDrawPrize.insert();
            }
        }
        taskPlan.updateById();
        if (NumberUtil.isGreater(moreThanPlan, BigDecimal.ZERO)) {
            this.finishTask(userInfo, type, taskType, linkId, collectionId, moreThanPlan);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addDrawPrize(Long userId, Long mysticId, Long pledgeId, String name, List<DrawPrizeDTO> prizeDTOS, DrawPriceTypeEnum drawPriceTypeEnum) {
        Assert.isFalse(ObjectUtil.hasNull(userId, mysticId, pledgeId, name), () -> new GlobalRunTimeException("添加奖励参数不正确"));
        Assert.notEmpty(prizeDTOS, () -> new GlobalRunTimeException("奖励不正确"));
        log.info("秘境发放奖励 userId:{}.mysticId(秘境Id):{},pledgeId(质押Id):{},name:{},prizeDTOS:{}", userId, mysticId, pledgeId, name, prizeDTOS);
        int count = taskDrawPrizeDao.getCount(mysticId, pledgeId, drawPriceTypeEnum);
        if (count > 0) {
            throw new GlobalRunTimeException("该秘境奖励已发放过了");
        }
        for (DrawPrizeDTO prizeDTO : prizeDTOS) {
            TaskDrawPrize taskDrawPrize = new TaskDrawPrize();
            taskDrawPrize.setTaskId(mysticId);
            taskDrawPrize.setDrawType(drawPriceTypeEnum);
            taskDrawPrize.setTaskPlanId(pledgeId);
            taskDrawPrize.setUserId(userId);
            taskDrawPrize.setTaskName(name);
            taskDrawPrize.setPrizeType(prizeDTO.getPrizeType());
            if (prizeDTO.getPrizeType() == TaskPrizeTypeEnum.INTEGRAL) {
                taskDrawPrize.setProductIcon("https://cdn.gometa.com.cn/scnft/default/integral.png");
            } else if (prizeDTO.getPrizeType() == TaskPrizeTypeEnum.PROPS) {
                EquityProps equityProps = equityPropsDao.getById(prizeDTO.getEquityId());
                if (ObjectUtil.isNull(equityProps)) {
                    throw new GlobalRunTimeException("虚拟道具Id不正确");
                }
                taskDrawPrize.setEquityId(equityProps.getId());
                taskDrawPrize.setProductIcon(equityProps.getCreationContent());
            } else {
                throw new GlobalRunTimeException("奖励类型不正确");
            }
            taskDrawPrize.setStatus(false);
            taskDrawPrize.setPrizeCount(prizeDTO.getPrizeCount());
            taskDrawPrize.insert();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exchangeBox(UserInfo userInfo, Long id, int num) {
        if (!userInfo.getIsSm()) {
            throw new GlobalRunTimeException("请先进行实名认证");
        }
        BoxTakePool boxTakePool = boxTakePoolDao.getById(id);
        Assert.notNull(boxTakePool, () -> new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
        Assert.isTrue(boxTakePool.getStatus(), () -> new GlobalRunTimeException(ErrorCode.PRODUCT_HAS_BEEN_DESCONTINUED));
        DigitalCollectionProductInfo box = digitalCollectionProductInfoDao.getById(boxTakePool.getProductBoxId());
        Assert.notNull(box, () -> new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
        BoxGroupVO boxGroupVO = userCollectionDao.boxGroupUser(userInfo.getId(), box.getRelationId(), id);
        //是否在允许购买的时间内
        //判定时间是否在允许时间段内
        Date now = new Date();
        //设置的开始和结束时间不为空，且当前时间不在两个时间段内则无法购买，历史老商品未配置时间段的则为永久出售不做限制 区分已结束、未开始
        if (null != box.getBeginTime() && null != box.getEndTime()) {
            if (now.before(box.getBeginTime())) {
                throw new GlobalRunTimeException("兑换活动未开始");
            }
            if (now.after(box.getEndTime())) {
                throw new GlobalRunTimeException("兑换活动已结束");
            }
        }
        //判断是否已达兑换上限
        if (Objects.nonNull(boxGroupVO) && boxGroupVO.getCount() >= boxTakePool.getUpperLimit()) {
            throw new GlobalRunTimeException(ErrorCode.EXCHANGE_CAP);
        }

        if (box.getIsRegisterTime()) {
            Assert.isTrue(userInfo.getCreateTime().after(box.getRegisterBeginTime()), () -> new GlobalRunTimeException("注册时间不符合"));
            Assert.isTrue(userInfo.getCreateTime().before(box.getRegisterEndTime()), () -> new GlobalRunTimeException("注册时间不符合"));
        }

        for (int i = 0; i < num; i++) {
            Assert.isTrue(box.getTypeClassify() == ClassifyType.BLIND_BOX, () -> new GlobalRunTimeException(ErrorCode.BOX_ONLY_EXCHANGE));
            ProductStock productStock = productStockDao.getProductStock(box.getId(), box.getRelationId(), null);
            if (productStock.getUsableCount() <= 0 || box.getIsSoldOut()) {
                throw new GlobalRunTimeException(ErrorCode.COLLECTION_IS_SOLD_OUT);
            }

            WhetherUserMeetsRedemptionConditionsVO satisfactoryConvertibility = boxTakeConversionConditionService.whetherUserMeetsRedemptionConditions(userInfo.getId(), boxTakePool.getId(), 1);
            if (!satisfactoryConvertibility.comparison()) {
                throw new GlobalRunTimeException("不满足兑换条件");
            }
            productStockService.subIntegralStock(box.getId(), box.getRelationId(), null, 1, userInfo.getId(), CommodityType.BOX_DRAW);

            // 随机盲盒.
            BoxItem boxItem = boxItemService.openBox(box.getId(), box.getRelationId());
            //减去盲盒库存
            productStockService.subIntegralStock(box.getId(), box.getRelationId(), boxItem.getId(), 1, userInfo.getId(), CommodityType.BOX_DRAW);


            //增加兑换记录
            BoxExchange boxExchange = new BoxExchange();
            boxExchange.setUserId(userInfo.getId());
            boxExchange.setBoxProductId(boxTakePool.getId());
            boxExchange.setExchangeTime(DateTime.now());
//        boxExchange.setCostQuantity(boxTakePool.getCostQuantity() * num);
            boxExchange.setExchangeMix(satisfactoryConvertibility.exchangeMix());
            boxExchange.setBoxCount(1);
            boxExchange.insert();
            DigitalCollection collection = digitalCollectionDao.getById(boxItem.getCollectionId());
            Assert.notNull(collection, () -> new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
            BoxProduct boxProduct = boxProductDao.getById(box.getRelationId());
            Assert.notNull(boxProduct, () -> new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
            if (satisfactoryConvertibility.whetherEquityPropsAreNeeded()) {
                List<QueryBoxConditionVO> equityProps = satisfactoryConvertibility.screen(2, BoxConditionEnum.EQUITY_PROPS);
                equityProps.forEach(queryBoxConditionVO -> {
                    equityPropsService.subVoucher(queryBoxConditionVO.getTripartiteId(), userInfo.getId(), Convert.toInt(queryBoxConditionVO.getCostQuantity()) * 1, StrUtil.format("{}x{}", boxProduct.getFirstTitle(), 1), boxExchange.getId(), EquityPropsTypeEnum.VOUCHER, EquityPropsTypeEnum.VIRTUAL_PROPS, EquityPropsTypeEnum.RAFFLE_TICKET);
                });
            }

            if (satisfactoryConvertibility.whetherFragmentsAreNeeded()) {
                List<QueryBoxConditionVO> starFragment = satisfactoryConvertibility.screen(2, BoxConditionEnum.STAR_FRAGMENT);
                starFragment.forEach(queryBoxConditionVO -> {
                    userAssetsService.subIntegralByUserId(Convert.toBigDecimal(queryBoxConditionVO.getCostQuantity()).multiply(Convert.toBigDecimal(1)), userInfo.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.BOX_EXCHANGE, boxProduct.getId(), StrUtil.format("{}x{}", boxProduct.getFirstTitle(), 1));
                });
            }

            //生态积分
            if (satisfactoryConvertibility.whetherEcologyPoolPointsNeeded()) {
                List<QueryBoxConditionVO> ecologyPools = satisfactoryConvertibility.screen(2, BoxConditionEnum.ECOLOGY_POOL_POINTS);
                ecologyPools.forEach(queryBoxConditionVO -> {
                    ecologyPoolService.convertPoints(Convert.toBigDecimal(queryBoxConditionVO.getCostQuantity()).multiply(Convert.toBigDecimal(1)), boxTakePool.getDaoId(), userInfo.getId());
                });
            }

            //添加藏品
            userCollectionService.addCollectionForExchange(userInfo.getId(), null, collection.getId(), IdUtil.getSnowflakeNextIdStr(), collection.getCreationContent(), collection.getLevel(), collection.getFirstTitle(),
                    collection.getUserCreatorId(), ReceivedCollectionType.BOX_EXCHANGE, boxProduct.getId(), boxProduct.getFirstTitle(), boxProduct.getCreationContent(), false, box.getId(), 0L, 0L, box.getProductNum(), 0, null, null, AddCollectionEnum.STAIR, id);

            //扣减虚拟道具
            //插入藏品流转记录
            CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
            collectionCirculatingRecord.setCommodityType(CommodityType.INTEGRAL_PRODUCT);
            collectionCirculatingRecord.setTypeClassify(box.getTypeClassify());
            collectionCirculatingRecord.setUserId(userInfo.getId());
            collectionCirculatingRecord.setCollectionId(collection.getId());
            collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.BOX_EXCHANGE);
            collectionCirculatingRecord.setUserReceiveIntegraId(id);
            collectionCirculatingRecord.insert();
        }


    }


    /**
     * 获取今日所有任务
     *
     * @return
     */
    private Map<ParticipantsEnum, List<Task>> getTodayTask() {
        return taskDao.getTodayTask(6L).stream().collect(Collectors.groupingBy(Task::getParticipants));
    }

    private Map<ParticipantsEnum, List<Task>> getTodayTask(TaskTypeEnum taskType) {
        return taskDao.getTodayTask(taskType.getCode()).stream().collect(Collectors.groupingBy(Task::getParticipants));
    }

    private Map<ParticipantsEnum, List<Task>> getTodayTask(Boolean isAudit) {
        return taskDao.getTodayMerchantTask().stream().collect(Collectors.groupingBy(Task::getParticipants));
    }

}